# -*- coding: utf-8 -*-
"""
@FileName：main_window.py
@Description：
@Author：锦沐Python
@Time：2024/8/23 21:39
"""
import tkinter as tk
from tkinter import ttk, filedialog, messagebox
from Media.src.config import *
from ttkbootstrap import Style
from Media.src.video_player import VideoPlayer
from Media.src.video_record import VideoRecord


class MainWindow:
    """
    绘制 tk 程序 Ui
    """
    def __init__(self, title):
        # 创建 Tk 窗口
        self.window = tk.Tk()
        # 设置窗口标题
        self.window.title(title)
        # 图标
        self.icon_img = tk.PhotoImage(file=ICON)
        self.window.iconphoto(True, self.icon_img)
        # 窗口大小
        self.window.geometry(WIN_SIZE)
        self.window.minsize(WIN_MIN_WIDTH, WIN_MIN_HEUGHT)
        # 设置黑色主题
        Style(theme=THEME_STYLE)
        # 视频路径列表
        self.video_source_list = []
        # 当前视频索引
        self.video_source = ""
        # 当前视频进度
        self.process_var = tk.IntVar(self.window, value=0)
        # 文件保存路径
        self.video_save_path = SAVE_VIDEO_PATH
        # 当前功能状态
        self.mode_state = VIDEO_PLAY
        # 初始化布局
        self._create_containers()
        # 填充部件
        self._fill_containers()
        # 初始化播放器
        self.video_play = None
        # 初始化摄像
        self.video_record = None
        # 激活画布更新函数, UPDATE_TIME ms 更新一次，不要使用多线程，多线程会导致画面严重闪烁
        self.update_time = UPDATE_TIME
        self._update()

    def _update(self):
        if self.video_record and self.mode_state == VIDEO_RECORD:
            self.video_record.update()

        if self.video_play and self.mode_state == VIDEO_PLAY:
            self.video_play.update()
            # 刷新进度条
            self.process_var.set(self.video_play.get_current_progress())

        self.window.after(self.update_time, self._update)

    def _create_containers(self):
        # 左边容器
        self.left_frame = ttk.Frame(self.window)
        self.left_frame.pack(side=tk.LEFT, expand=True, fill=tk.BOTH, ipady=5, ipadx=5)

        # 右边容器
        self.right_frame = ttk.Frame(self.window, width=200)
        self.right_frame.pack(side=tk.RIGHT, fill=tk.Y, ipady=5, ipadx=5)

    def _fill_containers(self):
        ############################# 左边 ########################################
        # 视频显示画布
        self.video_canvas = tk.Canvas(self.left_frame, borderwidth=4)
        self.video_canvas.pack(side=tk.TOP, fill=tk.BOTH, expand=True)

        self.process_bar = ttk.Scale(self.left_frame, from_=0, to=100,
                                     variable=self.process_var, command=self.on_progress_change)
        self.process_bar.pack(side=tk.TOP, fill=tk.X, expand=False, padx=5, pady=5)

        # 按钮容器
        self.control_frame = ttk.Frame(self.left_frame)
        self.control_frame.pack(side=tk.BOTTOM, expand=False, fill=tk.X, ipady=5, ipadx=5)

        # 保持对 PhotoImage 对象的引用
        self.img_forward = tk.PhotoImage(file=FORWARD_PATH)
        self.forword_button = ttk.Button(self.control_frame, image=self.img_forward,
                                         style=BUTTON_STYLE, command=self.switch_forward_video)
        self.forword_button.pack(side=tk.LEFT, padx=5, expand=True)

        self.img_play = tk.PhotoImage(file=PLAY_PATH)
        self.img_pause = tk.PhotoImage(file=PAUSE_PATH)

        self.play_button = ttk.Button(self.control_frame, image=self.img_play,
                                      style=BUTTON_STYLE, command=self.play_change)
        self.play_button.pack(side=tk.LEFT, padx=5, expand=True)

        self.img_next = tk.PhotoImage(file=NEXT_PATH)
        self.next_button = ttk.Button(self.control_frame, image=self.img_next,
                                      style=BUTTON_STYLE, command=self.switch_next_video)
        self.next_button.pack(side=tk.LEFT, padx=5, expand=True)

        ################################# 右边 ####################################
        # 右边控制栏
        self.tip1_label = ttk.Label(self.right_frame, text="录像", anchor=tk.CENTER)
        self.tip1_label.pack(fill=tk.X, side=tk.TOP, expand=True)

        # 录制控件
        self.record_control_frame = ttk.Frame(self.right_frame)
        self.record_control_frame.pack(fill=tk.X, expand=True)

        self.img_start = tk.PhotoImage(file=START_PATH)
        self.img_path = tk.PhotoImage(file=PATH_PATH)
        self.record_button = ttk.Button(self.record_control_frame, image=self.img_start,
                                        style=BUTTON_STYLE, command=self.record_change)
        self.record_button.pack(side=tk.LEFT, expand=True)

        self.img_end = tk.PhotoImage(file=END_PATH)
        self.record_end_button = ttk.Button(self.record_control_frame, image=self.img_end,
                                            style=BUTTON_STYLE, command=self.record_end)
        self.record_end_button.pack(side=tk.LEFT, expand=True)

        self.open_dir_button = ttk.Button(self.right_frame, text="打开文件夹", command=self.open_dir)
        self.open_dir_button.pack(fill=tk.X, expand=True)

        self.file_list_text = ttk.Treeview(self.right_frame, columns="File", show="headings")
        self.file_list_text.heading("File", text="Files")
        # 绑定 Treeview 点击事件
        self.file_list_text.bind("<ButtonRelease-1>", self.on_item_click)
        self.file_list_text.pack(expand=True, fill=tk.Y, pady=5, side=tk.BOTTOM)

    def run_app(self):
        """
        启动窗口主循环
        """
        self.window.mainloop()

    def play_change(self):
        """
        切换播放模式
        :return:
        """
        if self.video_play is None:
            self.show_msg(msg="请先选择视频文件夹", code=500)
            return

        self.change_mode(mode=VIDEO_PLAY)

        # 播放状态切换
        if self.video_play.is_playing:
            self.play_button.config(image=self.img_play)
            self.video_play.pause()
        else:
            self.video_play.resume()
            self.play_button.config(image=self.img_pause)
            self.video_play.play()

    def on_progress_change(self, value):
        """
        变更视频进度
        :param value:
        """
        # print(f"进度条的值改变了: {type(value)}")
        if self.video_play:
            self.video_play.set_start(float(value) / 100)

    @mode_wrapper(VIDEO_PLAY)
    def switch_forward_video(self):
        """
        切换上一部视频
        """
        self.close_video_player()
        if self.video_source_list:
            source_index = (self.video_source_list.index(self.video_source) - 1) % len(self.video_source_list)
            self.video_source = self.video_source_list[source_index]
            self.video_play = VideoPlayer(self.video_canvas, self.video_source)
            self.process_var.set(0)
            self.play_change()
        else:
            self.show_msg(msg="请先选择视频文件夹", code=500)

    @mode_wrapper(VIDEO_PLAY)
    def switch_next_video(self):
        """
        切换下一部视频
        """
        self.close_video_player()
        if self.video_source_list:
            source_index = (self.video_source_list.index(self.video_source) + 1) % len(self.video_source_list)
            self.video_source = self.video_source_list[source_index]
            self.video_play = VideoPlayer(self.video_canvas, self.video_source)
            self.process_var.set(0)
            self.play_change()
        else:
            self.show_msg(msg="请先选择视频文件夹", code=500)

    def open_dir(self):
        """
        打开文件夹对话框，挑选视频文件夹
        """
        folder_path = filedialog.askdirectory()

        if folder_path:
            # 更新 Treeview
            self.file_list_text.delete(*self.file_list_text.get_children())
            self.video_source_list.clear()

            # 获取视频文件列表
            video_extensions = (".mp4", ".avi")  # 根据需要添加更多扩展名
            for file in Path(folder_path).glob("*"):
                if file.suffix in video_extensions:
                    # 路径保存
                    self.video_source_list.append(str(file))
                    # 只显示文件名
                    self.file_list_text.insert("", "end", values=(file.name,))

            # 初始化当前播放文件路径
            self.video_source = self.video_source_list[0]
            self.change_mode(mode=VIDEO_PLAY)

    @mode_wrapper(VIDEO_PLAY)
    def on_item_click(self, event):
        """
        获取点击事件
        :param event:
        """
        # 获取被点击的列表项
        item = self.file_list_text.identify("item", event.x, event.y)
        if item:
            # 关闭上一个视频
            self.close_video_player()
            # 获取目标下标
            clicked_index = self.file_list_text.index(item)
            # 获取目标文件路径
            self.video_source = self.video_source_list[clicked_index]
            self.video_play = VideoPlayer(self.video_canvas, self.video_source)
            self.process_var.set(0)
            # 初始化播放器
            self.play_change()

            print(f"Clicked on: {clicked_index}")
            print(f"Index of clicked item: {self.video_source}")

    def record_change(self):
        """
        录制状态切换
        """
        self.change_mode(mode=VIDEO_RECORD)

        if self.video_record is None:
            # 初始化摄像
            self.video_record = VideoRecord(self.video_canvas, self.video_save_path)

        if self.video_record.is_recording:
            self.record_button.config(image=self.img_start)
            self.video_record.pause_record()
        else:
            self.record_button.config(image=self.img_path)
            self.video_record.start_record()
            self.video_record.resume_record()

    @mode_wrapper(VIDEO_RECORD)
    def record_end(self):
        """
        结束录制
        """
        self.close_video_record()

    def show_msg(self, title="提示", msg="什么也没有", code=200):
        """
        提示弹窗
        :param title: 弹窗标题
        :param msg: 内容
        :param code: 200 | 300 | 500
        """
        if code == 200:
            messagebox.showinfo(title=title, message=msg)
        elif code == 500:
            messagebox.showerror(title=title, message=msg)
        elif code == 300:
            messagebox.showwarning(title=title, message=msg)

    def change_mode(self, mode):
        """
        变换模式
        :param mode: VIDEO_PLAY | VIDEO_RECORD
        """
        if mode == VIDEO_PLAY:
            if self.video_source and self.video_source_list:
                self.mode_state = mode
                self.close_video_record()
            else:
                self.show_msg(msg="请先打开一个视频文件夹 或 结束录制", code=500)

        elif mode == VIDEO_RECORD:
            if self.video_save_path:
                self.mode_state = mode
                self.close_video_player()
            else:
                self.show_msg(msg="保存路径不存在", code=500)

    def close_video_player(self):
        """
        关闭播放模式
        """
        if self.video_play:
            self.video_play.close()
            self.video_play = None
            self.process_var.set(0)
            self.play_button.config(image=self.img_play)

    def close_video_record(self):
        """
        关闭录制模式
        """
        if self.video_record:
            self.video_record.end_record()
            self.video_record = None
            self.process_var.set(0)
            self.record_button.config(image=self.img_start)
